/*
* Created by boil on 2024/01/01.
*/

#ifndef RENDU_ASYNC_CANCELLATION_TOKEN_HPP
#define RENDU_ASYNC_CANCELLATION_TOKEN_HPP

#include "async_define.h"

ASYNC_NAMESPACE_BEGIN

class cancellation_source;
class cancellation_registration;

namespace detail {
  class cancellation_state;
}

class cancellation_token {
public:
  /// Construct to a cancellation token that can't be cancelled.
  cancellation_token() noexcept;

  /// Copy another cancellation token.
  ///
  /// New token will refer to the same underlying state.
  cancellation_token(const cancellation_token &other) noexcept;

  cancellation_token(cancellation_token &&other) noexcept;

  ~cancellation_token();

  cancellation_token &operator=(const cancellation_token &other) noexcept;

  cancellation_token &operator=(cancellation_token &&other) noexcept;

  void swap(cancellation_token &other) noexcept;

  /// Query if it is possible that this operation will be cancelled
  /// or not.
  ///
  /// Cancellable operations may be able to take more efficient code-paths
  /// if they don't need to handle cancellation requests.
  bool can_be_cancelled() const noexcept;

  /// Query if some thread has requested cancellation on an associated
  /// cancellation_source object.
  bool is_cancellation_requested() const noexcept;

  /// Throws cppcoro::operation_cancelled exception if cancellation
  /// has been requested for the associated operation.
  void throw_if_cancellation_requested() const;

private:
  friend class cancellation_source;
  friend class cancellation_registration;

  cancellation_token(detail::cancellation_state *state) noexcept;

  detail::cancellation_state *m_state;
};

inline void swap(cancellation_token &a, cancellation_token &b) noexcept {
  a.swap(b);
}
ASYNC_NAMESPACE_END

#endif
